/*
    C++11多线程库中packaged_task的使用
    packaged_task: 是一个类模板，用于将函数打包成一个可调用任务对象
    packaged_task和async区别
        1. packaged_task和async都可以将一个函数作为一个任务度执行或者调用，然后在异步线程中可以通过之前get_future()获取的future对象来获取结果
        2. 但是packaged_task是类模板，需要手动创建线程，然后去调用，而async是函数模板，自动创建线程，管理线程
*/

#include <iostream>
#include <future>
#include <thread>

int add(int num1, int num2)
{
    return num1 + num2;
}

int main()
{
    std::packaged_task<int(int, int)> task(add);
    std::future<int> future = task.get_future();
    task(1, 2); // task对象可以跟函数一样调用


    // 但是task对象不能直接当作实参去传递，想要直接当作参数传递
    // 因为它是一个只能移动的对象，它不支持拷贝构造和拷贝赋值。
    // 当你直接将task作为参数传递给std::thread时，编译器会尝试拷贝task
    // 但由于std::packaged_task不支持拷贝，所以会编译失败。

    // 解决方案：
    // 1. 使用std::move()将task对象移动到线程中
    // 2. 使用std::shared_ptr将task对象封装起来，并传递给线程
    // std::thread t(std::move(task), 1, 2);
    std::shared_ptr<std::packaged_task<int(int, int)>> task_ptr = std::make_shared<std::packaged_task<int(int, int)>>(add);
    std::thread t([&task_ptr](){
        (*task_ptr)(1, 2);
    });

    std::cout << future.get() << std::endl;
    t.join();
    return 0;
}